package com.bfd.es_demo.config;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;

import org.elasticsearch.rest.RestStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;


@Component
public class ElasticsearchUtil {
    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchUtil.class);


    @Resource(name="restHighLevelClient")
    private RestHighLevelClient restHighLevelClient;

    private static RestHighLevelClient client;

    private static ObjectMapper mapper = new ObjectMapper();

    /**
     * @PostContruct是spring框架的注解
     * spring容器初始化的时候执行该方法
     */
    @PostConstruct
    public void init() {
        client = this.restHighLevelClient;
    }
    /**
     * 创建索引
     *
     * @param index
     * @return
     */
    public static boolean createIndex(String index) {
        //index名必须全小写，否则报错
        CreateIndexRequest request = new CreateIndexRequest(index);
        //索引配置setting
        request.settings(Settings.builder().put("index.number_of_shards",5)
                .put("index.number_of_replicas", 2) // 副本数
                .put("analysis.analyzer.default.tokenizer","standard"));
        try {
            CreateIndexResponse indexResponse = client.indices().create(request);
            if (indexResponse.isAcknowledged()) {
                LOGGER.info("创建索引成功");
            } else {
                LOGGER.info("创建索引失败");
            }
            return indexResponse.isAcknowledged();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * 插入数据
     * @param index
     * @param type
     * @param object
     * @return
     */
    public static String addData(String index, String type, String id, JSONObject object) throws IOException {
        IndexRequest indexRequest = new IndexRequest(index, type, id);
        try {
            indexRequest.source(mapper.writeValueAsString(object), XContentType.JSON);
            IndexResponse indexResponse = client.index(indexRequest);
            if(indexResponse!=null){
                long version = indexResponse.getVersion();
                if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
                    LOGGER.info("新增文档成功!"+"\nindex:"+indexResponse.getIndex()+"\ntype"+indexResponse.getType()+"\nid"+indexResponse.getId());
                } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
                    LOGGER.info("修改文档成功!"+"\nindex:"+indexResponse.getIndex()+"\ntype"+indexResponse.getType()+"\nid"+indexResponse.getId());
                }
            }
            return indexResponse.getId();
        } catch (ElasticsearchException e) {
            if(e.status() == RestStatus.CONFLICT){
                LOGGER.error("冲突了\n"+e.getDetailedMessage());
            }
            LOGGER.error("索引异常"+e);
        } catch (JsonProcessingException e) {
            LOGGER.error("JSON==>XContentType.JSON"+e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }
        client.close();
        return null;
    }

    /**
     * 根据id查询数据
     * @param index
     * @param type
     * @param id
     * @return
     * @throws IOException
     */
    public static Object getData(String index, String type, String id) throws IOException {
        //创建文档请求
        GetRequest request = new GetRequest(index,type,id);
        GetResponse result = null;
        //可选设置
        //request.routing();
        //request.version();
        //request.fetchSourceContext(new FetchSourceContext(false)); //是否获取_source字段
        //选择返回的字段
        //使用  FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);
        //查询所有字段
        try {
            result = client.get(request, RequestOptions.DEFAULT);
            if(result!=null){
                long version = result.getVersion();
                if (result.isExists()) {
                    LOGGER.info("此id信息存在!"+"\nindex:"+result.getIndex()+"\ntype"+result.getType()+"\nid"+result.getId());
                }
                LOGGER.info("未找到此id信息"+"\nindex:"+result.getIndex()+"\ntype"+result.getType()+"\nid"+result.getId());

            }
        } catch (ElasticsearchException  e) {
            if (e.status() == RestStatus.NOT_FOUND) {
                LOGGER.error("没有找到该id的文档" );
            }
            if (e.status() == RestStatus.CONFLICT) {
                LOGGER.error("获取时版本冲突了，请在此写冲突处理逻辑！" );
            }
            LOGGER.error("获取文档异常", e);
        }finally {
            client.close();
        }
        return result.getSource();
    }
    public static String addDataByBulk(String index, String type, ArrayList<JSONObject> list,String str) throws JsonProcessingException {
        BulkRequest bulkRequest = new BulkRequest();
        for (JSONObject i:list){
            bulkRequest.add(new IndexRequest(index,type,i.getString(str)).source(mapper.writeValueAsString(i), XContentType.JSON));
        }
        // 2、可选的设置
            /*
            request.timeout("2m");
            request.setRefreshPolicy("wait_for");
            request.waitForActiveShards(2);
            */
        // 同步请求
        /*try {
            BulkResponse bulkResponse = client.bulk(bulkRequest);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        //异步请求
        ActionListener<BulkResponse> listener = new ActionListener<BulkResponse>() {
            @Override
            public void onResponse(BulkResponse bulkResponse) {
                if(bulkResponse!=null) {
                    for (BulkItemResponse bulkItemResponse : bulkResponse) {
                        DocWriteResponse itemResponse = bulkItemResponse.getResponse();
                        if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX
                                || bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) {
                            IndexResponse indexResponse = (IndexResponse) itemResponse;
                            //TODO 新增成功的处理
                            LOGGER.info("新增成功");

                        } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) {
                            UpdateResponse updateResponse = (UpdateResponse) itemResponse;
                            //TODO 修改成功的处理
                            LOGGER.info("修改成功");

                        } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) {
                            DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
                            //TODO 删除成功的处理
                            LOGGER.info("删除成功");
                        }
                    }
                }
            }

            @Override
            public void onFailure(Exception e) {

            }
        };
        client.bulkAsync(bulkRequest,listener);
        return "操作成功";
    }


    /**
     * 检查索引
     * @param index
     * @return
     * @throws IOException
     */
    public static boolean checkIndexExist(String index) {
        try {
            Response response = client.getLowLevelClient().performRequest("HEAD", index);
            boolean exist = response.getStatusLine().getReasonPhrase().equals("OK");
            return exist;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 获取低水平客户端
     * @return
     */
    public static RestClient getLowLevelClient() {
        return client.getLowLevelClient();
    }
//https://www.cnblogs.com/wangzhuxing/p/9609127.html#_label3_3
}
